package com.game.modular.game.playerMatch.service;

import com.game.comment.exection.ServiceException;
import com.game.modular.game.playerAssets.domain.PlayerHero;
import com.game.modular.game.playerAssets.domain.PvpRanks;
import com.game.modular.game.playerAssets.mapper.AccountRanksMapper;
import com.game.modular.game.playerAssets.service.PlayerHeroServiceImpl;
import com.game.modular.game.playerInfo.domain.Player;

import com.game.modular.game.playerInfo.service.PlayerServiceImpl;
import com.game.modular.game.playerMatch.service.base.PvpRanksBaseServiceImpl;
import com.game.modular.gameCore.map.domain.CoreCityLink;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 武将队伍(PvpRanks)表服务实现类
 *
 * @author cxy
 * @since 2024-07-18 11:19:32
 */
@Validated
@Slf4j
@Service
public class PvpRanksServiceImpl extends PvpRanksBaseServiceImpl {
    @Resource
    private AccountRanksMapper accountRanksMapper;
    @Resource
    private PlayerHeroServiceImpl getHeroService;
    @Resource
    private PvpCityServiceImpl pvpCityServiceImpl;
    @Resource
    private PlayerServiceImpl accountServiceImpl;
    @Resource
    private PlayerMatchServiceImpl playerMatchServiceImpl;
    @Resource
    private ValueOperations<Object, Object> valueOperations;

    public void init(Long playerId) {
        List<PvpRanks> values = list(playerId);
        if (values.size() != 5) {
            for (long i = 0; i < 5; i++) {
                PvpRanks build = PvpRanks.builder()
                        .uid(playerId)
                        .cityId(0L)
                        .rankNo(i + 1)
                        .heroId1(0L)
                        .heroId2(0L)
                        .heroId3(0L)
                        .status(1)
                        .build();
                save(build);
            }
        }
    }

    /**
     * 刷新 pvp队伍|清空队伍兵力
     * @param playerId
     */
    public void resetPvp(Long playerId) {
        List<PvpRanks> values = list(playerId);
        List<PvpRanks> collect = values.stream().peek(item -> {
            List<PlayerHero> wuJiang = getWuJiang(playerId, item.getRankNo());
            for (PlayerHero playerHero : wuJiang) {
                if (playerHero.getCurrentForce()!=0){
                    playerHero.clear();
                    getHeroService.updateById(playerHero);
                }
            }
            item.setCityId(0L);
            item.setHeroId1(0L);
            item.setHeroId2(0L);
            item.setHeroId3(0L);
            savaCache(item);
        }).collect(Collectors.toList());
        savaCache(playerId, listToMap(collect));
    }

    public void updateBy(Long playerId, Long rankNo, PvpRanks item) {
        savaCache(item);
    }

    public List<PlayerHero> getWuJiang(Long uid, Object ranksNo) {
        PvpRanks accountRanks = select(uid, ranksNo);
        return accountRanks.obtainCoreHeroIds().stream().map(item -> getHeroService.select(uid,item)).collect(Collectors.toList());
    }

    /**
     * 获取当前编队中还活着的武将
     *
     * @param uid
     * @param ranksNo
     * @return
     */
    public List<PlayerHero> obtainSurvivingGenerals(Long uid, Object ranksNo) {
        return getWuJiang(uid, ranksNo).stream().filter(item ->
                item.getCurrentForce() > 0
        ).collect(Collectors.toList());
    }


    public List<PvpRanks> formation(Long playerId, Long rankNo, Long heroId1, Long heroId2, Long heroId3) {
        List<Long> heroes = Arrays.asList(heroId1, heroId2, heroId3);
        for (Long heroId : heroes) {
            if (heroId != null && heroId != 0) {
                PlayerHero select = getHeroService.select(playerId, heroId);
                if (select == null) {
                    throw new ServiceException("武将不存在");
                }
            }
        }

        List<PvpRanks> ranksList = list(playerId);
        List<PvpRanks> collect = ranksList.stream().filter(item -> item.getStatus() == 2)
                .collect(Collectors.toList());

        if (collect.stream().anyMatch(item -> {
            Set<Long> heroIds = item.obtainCoreHeroIds();
            return heroIds.contains(heroId1) || heroIds.contains(heroId2) || heroIds.contains(heroId3);
        })){
            throw new ServiceException("存在战斗中的武将");
        }

        return ranksList.stream().peek(item -> {
            if (Objects.equals(item.getRankNo(), rankNo)) {
                item.setHeroId1(heroId1);
                getHeroService.updateRankOrder(playerId, heroId1, 1);
                item.setHeroId2(heroId2);
                getHeroService.updateRankOrder(playerId, heroId2, 2);
                item.setHeroId3(heroId3);
                getHeroService.updateRankOrder(playerId, heroId3, 3);
                item.setStatus(1);
            } else {
                if (heroes.contains(item.getHeroId1())) {
                    item.setHeroId1(0L);
                }
                if (heroes.contains(item.getHeroId2())) {
                    item.setHeroId2(0L);
                }
                if (heroes.contains(item.getHeroId3())) {
                    item.setHeroId3(0L);
                }
                item.setStatus(1);
            }
            updateBy(playerId, item.getRankNo(), item);
        }).sorted(Comparator.comparing(PvpRanks::getRankNo)).collect(Collectors.toList());
    }

    public PvpRanks uninstallation(
            Long playerId,
            Long rankNo
    ) {
        // 获取队伍
        PvpRanks accountRanks = this.select(playerId, String.valueOf(rankNo));
        if (accountRanks.getStatus() == 2) {
            throw new ServiceException("队伍正在战斗中,无法卸下武将");
        }
        accountRanks.setCityId(0L);
        accountRanks.setHeroId1(0L);
        accountRanks.setHeroId2(0L);
        accountRanks.setHeroId3(0L);
        updateById(accountRanks);
        return accountRanks;
    }

    public PvpRanks teamMovement(
            Long playerId,
            Long rankNo,
            Long targetCityId
    ) {
        PvpRanks select = select(playerId, rankNo);
        if (select == null)
            throw new ServiceException("队伍不存在");
        // 获取路线开销时间
        Long startCityId = select.getCityId();

        // 获取运输时间
        Player account = accountServiceImpl.select(playerId);
        // 判断对局
        Long currentMatchId = playerMatchServiceImpl.currentMatchId(playerId);
        CoreCityLink coreCityLink = pvpCityServiceImpl.bfsOwnerMinPaths(
                startCityId, targetCityId, Math.toIntExact(currentMatchId), playerId);
        Integer needTime = coreCityLink.getNeedTime();

        // 创建线程池
        ThreadFactory springThreadFactory = new CustomizableThreadFactory("----队伍移动-thread-pool----");
        ScheduledExecutorService scheduledExec = new ScheduledThreadPoolExecutor(5, springThreadFactory);
        scheduledExec.schedule(() -> {
            select.setCityId(targetCityId);
            updateById(select);
        }, needTime, TimeUnit.SECONDS);
        scheduledExec.shutdown();
        return select;
    }


    public void escape(Integer cityCoreId, Long escapePlayerId, Long winnerPlayerId, String attackRanksNo) {
        List<PvpRanks> accountRanks = list(escapePlayerId);
        if (accountRanks.isEmpty()) {
            throw new ServiceException("队伍不存在");
        }
        accountRanks.forEach(item -> {
            if (item.getCityId().equals(Long.valueOf(cityCoreId))) {
                item.setCityId(0L);
                updateBy(escapePlayerId, item.getRankNo(), item);
            }
        });
        PvpRanks winnerRanks = select(winnerPlayerId, attackRanksNo);
        winnerRanks.setCityId(Long.valueOf(cityCoreId));
        updateBy(winnerPlayerId, winnerRanks.getRankNo(), winnerRanks);
    }

    public Map<Long, List<PlayerHero>> getCityRanksHeroList(Long cityCoreId, Long ownerUid) {
        List<PvpRanks> pvpRanks = list(ownerUid).stream().filter(item -> item.getCityId().equals(cityCoreId)).collect(Collectors.toList());
        Map<Long, List<PlayerHero>> map = new HashMap<>();
        if (!pvpRanks.isEmpty()) {
            for (PvpRanks pvpRank : pvpRanks) {
                map.put(
                        pvpRank.getRankNo(),
                        obtainSurvivingGenerals(ownerUid, pvpRank.getRankNo().toString()).stream()
                                .peek(item -> item.setRankCamp(0))
                                .sorted(Comparator.comparing(PlayerHero::getRankOrder))
                                .collect(Collectors.toList())
                );
            }
        }
        return map;
    }
}
